package clue.editor;

import java.awt.Component;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JSpinner;
import javax.swing.JTextField;

import objects.BoardData;
import objects.Card;
import objects.CardType;
import objects.Character;
import objects.Envelope;
import objects.Player;
import objects.Room;
import objects.Weapon;

public class BoardDataParser {

	/**
	 * The method get board data and modify the frame accordingly
	 * @param boardData
	 */
	public static void parseBoardDataToFrame(BoardData boardData)
	{
		// Do not handle history (undo/redo) while parsing
		GlobalHistory.getInstance().setDisabled(true);
		
		JPanel innerPanel = (JPanel) ClueFrame.getInstance().getBoardPanel().getPlayersPanel().getPlayersInnerPanel();
		 
		ClueFrame.getInstance().getBoardPanel().getPlayersPanel().removeAllPlayers();
		

		if (boardData.getPlayers() != null)
		{
			PlayerPanel playerPanel2 = null;
	
			// Run over each player in the board data 
			for (Player player : boardData.getPlayers()) {
				
				// Create a new empty player panel
				playerPanel2 = new PlayerPanel(ClueFrame.getInstance().getBoardPanel().getPlayersPanel());
					
					// Check for each component on the frame whether the board data 
					// sets a value in it and set it
					for (Component component : playerPanel2.getComponents()) {
					
						if (component instanceof JCheckBox)
						{
							for (Card card : player.getCards()) 
							{
								if (card.getName().equals(((JCheckBox)component).getText()))
								{
									((JCheckBox)component).setSelected(true);
								}
							}
						}
						else if (component instanceof JComboBox)
						{
							((JComboBox<?>)component).setSelectedItem(player.getCharacter());
						}
						else if (component instanceof JTextField)
						{
							((JTextField) component).setText(player.getName());
						}
						else if (component instanceof JRadioButton && ((JRadioButton)component).getText().equals(player.getType()))
						{
							((JRadioButton) component).setSelected(true);
						}
						else if (component instanceof JSpinner)
						{
							((JSpinner)component).setValue(player.getOrder());
						}
					}
					
					innerPanel.add(playerPanel2);
					
					ClueFrame.getInstance().validate();
					innerPanel.repaint();
			}
		}
		
		JPanel envelopePanel = (JPanel) ClueFrame.getInstance().getBoardPanel().getEnvelopePanel().getComponent(1);
		
		// Create and set values to envelope panel according to the envelope in the board panel 
		if (boardData.getEnvelope() != null)
		{
			Character chosenCharacter = Character.valueOf(boardData.getEnvelope().getCharacterCard().getName());
			Room chosenRoom = Room.valueOf(boardData.getEnvelope().getRoomCard().getName());
			Weapon chosenWeapon = Weapon.valueOf(boardData.getEnvelope().getWeaponCard().getName());
			
			for (Component component : envelopePanel.getComponents()) 
			{
				if (component instanceof JComboBox)
				{
					Enum<?> enum1 = (Enum<?>) ((JComboBox<?>)component).getSelectedItem();
					
					if (enum1 instanceof Room)
					{
						((JComboBox<?>) component).setSelectedItem(chosenRoom);
					}
					else if (enum1 instanceof Weapon)
					{
						((JComboBox<?>) component).setSelectedItem(chosenWeapon);
					}
					else
					{
						((JComboBox<?>) component).setSelectedItem(chosenCharacter);
					}
				}
				
				ClueFrame.getInstance().validate();
				envelopePanel.repaint();
			}
		}
		else
		{
			for (Component component : envelopePanel.getComponents()) 
			{
				if (component instanceof JComboBox)
				{
					Enum<?> enum1 = (Enum<?>) ((JComboBox<?>)component).getSelectedItem();
					
					if (enum1 instanceof Room)
					{
						((JComboBox<?>) component).setSelectedItem(Room.values()[0]);
					}
					else if (enum1 instanceof Weapon)
					{
						((JComboBox<?>) component).setSelectedItem(Weapon.values()[0]);
					}
					else
					{
						((JComboBox<?>) component).setSelectedItem(Character.values()[0]);
					}
				}
				
				ClueFrame.getInstance().validate();
				envelopePanel.repaint();
			}
		}
		
		GlobalHistory.getInstance().setDisabled(false);
	}			
	
	/**
	 * The method creates a board data from the data in the frame
	 * @return
	 */
	public static BoardData parseFrameToBoardData()
	{
		JPanel innerPlayersPanel = (JPanel) ClueFrame.getInstance().getBoardPanel().getPlayersPanel().getPlayersInnerPanel();
		JPanel envelopePanel = (JPanel) ClueFrame.getInstance().getBoardPanel().getEnvelopePanel().getComponent(1);
		
		BoardData boardData = new BoardData();

		List<Player> playerList = new ArrayList<Player>();
		
		Component[] playerPanels = (Component[]) innerPlayersPanel.getComponents();
		
		// Run on all player panels and create a player to save in board data 
		for (int i = 0; i < playerPanels.length; i++) {
			
			Player player = new Player();
			
			List<Card> cards = new ArrayList<Card>();
			
			// Save for each component it's value in the player
			for (Component component : ((PlayerPanel)playerPanels[i]).getComponents()) 
			{
				if (component instanceof JCheckBox)
				{
					JCheckBox checkBox = (JCheckBox)component;
					
					if (checkBox.isSelected())
					{
						cards.add(createCard(checkBox.getText()));
					}
				}
				else if (component instanceof JComboBox)
				{
					@SuppressWarnings("unchecked")
					Object character = ((JComboBox<Character>)component).getSelectedItem();
					
					player.setCharacter((Character) character);
				}
				else if (component instanceof JTextField)
				{
					player.setName(((JTextField)component).getText());
				}
				else if (component instanceof JRadioButton && ((JRadioButton)component).isSelected())
				{
					player.setType(((JRadioButton)component).getText());
				}
				else if (component instanceof JSpinner)
				{
					player.setOrder((int) ((JSpinner)component).getValue());
				}
				
			}
			player.setCards(cards);
			playerList.add(player);
			
		}
		
		Envelope envelope = new Envelope();
		
		// Create an envelope from the data in the envelop panel
		for (Component component : envelopePanel.getComponents()) 
		{
			if (component instanceof JComboBox)
			{
				Enum<?> enum1 = (Enum<?>) ((JComboBox<?>)component).getSelectedItem();
				
				if (enum1 instanceof Room)
				{
					envelope.setRoomCard(new Card(CardType.ROOM, enum1.name()));
				}
				else if (enum1 instanceof Weapon)
				{
					envelope.setWeaponCard(new Card(CardType.WEAPON, enum1.name()));
				}
				else
				{
					envelope.setCharacterCard(new Card(CardType.CHARACTER, enum1.name()));
				}
			}
		}
		
		
		boardData.setPlayers(playerList);
		boardData.setEnvelope(envelope);
		
		return boardData;
	}
	
	private static Card createCard(String cardName)
	{
		Card card = new Card();
		
		for (Room room : Room.values()) {
			if (room.name().equals(cardName))
			{
				card.setName(cardName);
				card.setType(CardType.ROOM);
			}
		}
		
		for (Weapon weapon : Weapon.values()) {
			if (weapon.name().equals(cardName))
			{
				card.setName(cardName);
				card.setType(CardType.WEAPON);
			}
		}
		
		for (Character character : Character.values()) {
			if (character.name().equals(cardName))
			{
				card.setName(cardName);
				card.setType(CardType.CHARACTER);
			}
		}
		
		return card;
	}
	
	
	
}
